package com.unitd.frame.sso.common.parser.api;

import com.unitd.frame.comm.exception.EncryptException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;

/**
 * @desc 提供提取消息格式中的密文及生成回复消息格式
 * 用于加解密消息与xml之间的交互转换处理
 * @filename XMLParser.java
 * @copyright www.unitd.com
 * @author Hudan
 * @version 1.0
 * @date 2016/10/15
 */
public class XMLParser {

	/**
	 * @desc 将加密消息生成 XML 消息
	 * @param encrypt   加密后的消息密文
	 * @param signature 安全签名
	 * @param timeStamp 时间戳
	 * @param nonce     随机字符串
	 * @return 生成的加密后的XML字符串
	 */
	public static String generate(String encrypt, String signature, String timeStamp, String nonce) {
		StringBuffer format = new StringBuffer();
		format.append("<xml>\n");
		format.append("<Encrypt><![CDATA[%1$s]]></Encrypt>\n");
		format.append("<MsgSignature><![CDATA[%2$s]]></MsgSignature>\n");
		format.append("<TimeStamp>%3$s</TimeStamp>\n");
		format.append("<Nonce><![CDATA[%4$s]]></Nonce>\n");
		format.append("</xml>");
		return String.format(format.toString(), encrypt, signature, timeStamp, nonce);
	}

	/**
	 * @desc 提取出 XML 数据包中的加密消息
	 * @param xml 待提取的XML字符串
	 * @return 提取出的加密消息字符串
	 * @throws EncryptException {@link EncryptException}
	 */
	public static EncryptMsg extract(String xml) throws EncryptException {
		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			StringReader sr = new StringReader(xml);
			InputSource is = new InputSource(sr);
			Document document = db.parse(is);
			Element root = document.getDocumentElement();
			NodeList nodelist1 = root.getElementsByTagName("Encrypt");
			NodeList nodelist2 = root.getElementsByTagName("MsgSignature");
			NodeList nodelist3 = root.getElementsByTagName("TimeStamp");
			NodeList nodelist4 = root.getElementsByTagName("Nonce");

			/* 解析XML内容 */
			String encrypt = nodelist1.item(0).getTextContent();
			String signature = nodelist2.item(0).getTextContent();
			String timestamp = nodelist3.item(0).getTextContent();
			String nonce = nodelist4.item(0).getTextContent();
			return new EncryptMsg(encrypt, signature, timestamp, nonce);
		} catch (Exception e) {
			throw new EncryptException(EncryptException.ERROR_PARSE_XML, e);
		}
	}
}